#include "qqmusic.h"
#include "btform.h"
#include "ui_qqmusic.h"
#include "btform.h"
#include "commonpage.h"
#include "volumetool.h"
#include<QMouseEvent>
#include<QGraphicsDropShadowEffect>
#include<QDebug>
#include <QJsonObject>
#include <QVector>
#include <algorithm>  // 用于 std::random_shuffle
#include <QDir>
#include <QFileDialog>
#include<QString>
#include<QTimer>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include<QMessageBox>
QQMusic::QQMusic(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::QQMusic)
{
    ui->setupUi(this);

    initUI();
    initPlayer();
    initSQLite();
    initMusicList();
    connectSignalAndSlot();
}
//实现窗口移动功能--------------------------------------------------------
void QQMusic::mousePressEvent(QMouseEvent *event)
{
    //“按下左键”事件发生：记录拖动起始位置
    //event->button() == Qt::LeftButton：鼠标按下的事件是否由左键触发
    //event->button() 是一个成员函数调用，返回 Qt::MouseButton 枚举类型的值：
    //Qt::LeftButton 是一个枚举常量（enum），定义在 Qt 的命名空间 Qt 中
   if(event->button() == Qt::LeftButton)
       // event->button()返回触发当前事件的鼠标按钮
   {
       //event->globalPos():“鼠标按下”事件发生时，光标的位置
       //frameGeometry().topLeft()：“鼠标按下：事件发生时，窗口左上角位置
       //Geometry()不包含边框以及顶部标题区的范围
       //frameGeometry()包含边框以及顶部标题区的范围
       //event->globalPos()-frameGeometry().topLeft();//计算处光标与窗口左上角相较距离
       dragPosition = event->globalPos()-frameGeometry().topLeft();
       return;//按下左键后终止函数
   }
   //非左键按下时：交给父类处理
   QWidget::mousePressEvent(event);
}
void QQMusic::mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons() == Qt::LeftButton)
        //event->buttons()返回 当前所有被按住的鼠标按钮，需要检测 拖拽过程中是否有键被按住 的情况
        //鼠标移动时，可能同时按住多个键
    {
        // 计算鼠标移动的偏移量，并移动窗口
        // 新窗口位置 = 当前鼠标全局位置 - 初始偏移量
            move(event->globalPos() - dragPosition);
            //event->globalPos()当前光标的全局坐标
            //dragPosition之前记录的偏移量
            //通过move移动到新的位置，使得窗口左上角与光标之间的偏移保持为 dragPosition
        return;
    }
    //非左键按下时：交给父类处理
    QWidget::mouseMoveEvent(event);
}

void QQMusic::initUI()
{
    //设置无边框窗口，即窗口将来无标题栏
    this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
    //原边框作用：在常规窗口中，标题栏不仅显示窗口标题，还提供了窗口移动、缩放和关闭的交互区域
    //无边框窗口移除了这些标准界面元素，Qt不再自动处理窗口移动等操作
    //窗口管理器不再接收和转发相关的鼠标事件到应用程序

    // 设置BodyLeft中6个btForm的信息
    ui->stackedWidget->setCurrentIndex(4);
    curPage = ui->localPage;
    //-------------------------------设置主题窗口阴影---------------------------------
    //设置窗口背景透明
    this->setAttribute(Qt::WA_TranslucentBackground);//注意：需要加上命名空间域：Qt
    //QGraphicsDropShadowEffect为窗口添加投影效果

    //创建阴影对象shadowEffect
    QGraphicsDropShadowEffect* shadowEffect = new QGraphicsDropShadowEffect(this);
    //设置阴影偏移
    shadowEffect->setOffset(0,0);
    //设置阴影颜⾊：⿊⾊
    shadowEffect->setColor("#000000");
    // 设置阴影的模糊半径
    shadowEffect->setBlurRadius(10);
    //把阴影效果加入到窗口中
    this->setGraphicsEffect(shadowEffect);

    ui->Rec->seticon(":/rec.png", "推荐", 1);
    ui->music->seticon(":/music.png", "音乐馆", 2);
    ui->audio->seticon(":/radio.png", "电台", 3);
    ui->like->seticon(":/like.png", "我喜欢", 4);
    ui->local->seticon(":/local.png", "本地下载", 5);
    ui->Recent->seticon(":/recent.png", "最近播放", 6);

    //设置我喜欢、本地音乐、最近播放页面
    ui->likePage->setCommonPageUI("我喜欢", ":/ilikebg.png");
    ui->localPage->setCommonPageUI("本地音乐", ":/localbg.png");
    ui->recentPage->setCommonPageUI("最近播放", ":/recentbg.png");


    //本地下载BTForm动画默认显示
    ui->local->showAnimal();
    ui->stackedWidget->setCurrentIndex(4);

//-------------------------------设置随机数种子---------------------------------
    srand(time(NULL));
    //设置完随机数种子后再调用随机图片函数
    randomPiction();
    ui->recMusicBox->initRecBoxUi(randomPiction(),1);
    ui->supplyMusicBox->initRecBoxUi(randomPiction(),2);

    //创建音量调节窗口并且挂到对象树
   volumeTool = new VolumeTool(this);

   ui->likePage->setCommonPageUI("我喜欢", ":/ilikebg.png");
   ui->localPage->setCommonPageUI("本地音乐", ":/localbg.png");
   ui->recentPage->setCommonPageUI("最近播放", ":/recentbg.png");

   ui->play->setIcon(QIcon(":/play_2.png"));
   ui->playMode->setIcon(QIcon(":/shuffle_2.png"));

   ui->volumn->setIcon(QIcon(":/volumn.png"));
   ui->addLocal->setIcon(QIcon(":/add.png"));
   ui->playUp->setIcon(QIcon(":/up.png"));
   ui->playDown->setIcon(QIcon(":/down.png"));

   QGraphicsDropShadowEffect* _shadowEffect = new QGraphicsDropShadowEffect(this);
   _shadowEffect->setOffset(0, 0);
   _shadowEffect->setColor("#000000");
   _shadowEffect->setBlurRadius(20);
   this->setGraphicsEffect(shadowEffect);

   //实例化LrcWord对象
   lrcPage = new LrcPage(this);
   lrcPage->hide();
   lrcAnimation = new QPropertyAnimation(lrcPage, "geometry", this);
   lrcAnimation->setDuration(250);
   lrcAnimation->setStartValue(QRect(10, 10+lrcPage->height(),
   lrcPage->width(), lrcPage->height()));
   lrcAnimation->setEndValue(QRect(10, 10, lrcPage->width(), lrcPage->height()));


}
void QQMusic::initPlayer()
{
    //创建播放器:初始化媒体播放类
    player = new QMediaPlayer(this);
    //创建播放列表
    playList = new QMediaPlaylist(this);
    //将播放列表设置给播放器
    player->setPlaylist(playList);
    //设置播放模式：默认为循环播放
    playList->setPlaybackMode(QMediaPlaylist::Loop);

    //默认音量大小设置为20
    player->setVolume(20);
    connect(player, &QMediaPlayer::stateChanged, this, &QQMusic::onPlayStateChanged);
    connect(ui->playMode, &QPushButton::clicked, this, &QQMusic::onPlaybackModeCliked);
    connect(playList, &QMediaPlaylist::playbackModeChanged, this, &QQMusic::onPlaybackModeChanged);
    connect(playList, &QMediaPlaylist::currentIndexChanged, this, &QQMusic::onCurrentIndexChanged);
    //关联QMediaPlayer::durationChaged信号
    connect(player, &QMediaPlayer::durationChanged, this, &QQMusic::onDurationChanged);
    connect(player, &QMediaPlayer::positionChanged, this,  &QQMusic::onPositionChanged);

    connect(player,&QMediaPlayer::metaDataAvailableChanged,this,&QQMusic::onMetaDataAvailableChangedChanged);
}

void QQMusic::initSQLite()
{
    //1.链接数据库：导入数据库驱动
    sqlite = QSqlDatabase::addDatabase("QSQLITE");
    //2.设置数据库名称
    sqlite.setDatabaseName("QQMusic.db");
    //3.创建/打开数据库
    if(!sqlite.open())
    {
        QMessageBox::critical(this,"creat DB Error",sqlite.lastError().text());
        return;
    }
    else
    {
        qDebug()<<"--------------------------creat DB Successful!-----------------------------";
    }
    //4.创建数据库表
    QString sql = "CREATE TABLE IF NOT EXISTS musicInfo( \
            id INTEGER PRIMARY KEY AUTOINCREMENT, \
            musicId varchar(200) UNIQUE, \
            musicName varchar(50), \
            musicSinger varchar(50), \
            albumName varchar(50), \
            duration BIGINT, \
            musicUrl varchar(256), \
            isLike INTEGER, \
            isHistory INTEGER)";
    QSqlQuery query;
    if(!query.exec(sql))
       {
           QMessageBox::critical(this, "创建数据库表失败", query.lastError().text());
           return;
       }

    qDebug()<<"creat musicInfo tabel successful";
}

void QQMusic::initMusicList()
{
    // 1. 从数据库读取歌曲信息
        musicList.readFromDB();

        // 2. 更新CommonPage页面
        // 设置CommonPage的信息
        ui->likePage->setMusicListType(PageType::LIKE_PAGE);
        ui->likePage->reFresh(musicList);

        ui->localPage->setMusicListType(PageType::LOCAL_PAGE);
        ui->localPage->reFresh(musicList);

        ui->recentPage->setMusicListType(PageType::HISTORY_PAGE);
        ui->recentPage->reFresh(musicList);
}

QJsonArray QQMusic::randomPiction()
{
    // 推荐文本 + 推荐图片路径
        //创建存储“图片文件名”的字符串向量
        QVector<QString> vecImageName;
        vecImageName << "001.png" << "003.png" << "004.png" << "005.png" << "006.png"
                     << "007.png"
                     << "008.png" << "009.png" << "010.png" << "011.png" << "012.png"
                     << "014.png" << "015.png" << "016.png" << "017.png" << "018.png"
                     << "020.png" << "021.png" << "022.png" << "023.png" << "024.png"
                     << "026.png" << "027.png" << "028.png" << "029.png" << "030.png"
                     << "032.png" << "033.png" << "034.png" << "035.png" << "036.png"
                     << "038.png" << "039.png" << "040.png";

        // 使用std::random_shuffle算法随机打乱向量中元素的顺序
        //注意：要设置随机数种子
        std::random_shuffle(vecImageName.begin(), vecImageName.end());

       //创建QJsonAeeay对象存储结果
        QJsonArray objArray;
        //遍历打乱后的图片名称向量
        for (int i = 0; i < vecImageName.size(); ++i)
        {
            //创建QJsonObject对象用于存储单个推荐项
            QJsonObject obj;
            //项推向中插入图片路径
            obj.insert("path", ":/rec/" + vecImageName[i]);

            // 生成推荐文本，格式为"推荐-XXX"（XXX是三位数，不足补零）
            QString strText = QString("推荐-%1").arg(i, 3, 10, QChar('0'));
            //向对象中插入文本
            obj.insert("text", strText);

            //将对象添加到JSON数组当中
            objArray.append(obj);
        }
        //返回包含所有推荐项的JSON数组
        return objArray;
}

void QQMusic::playMusicByIndex_(CommonPage *page, int index)
{
    playAllOfCommonPage(page, index);

}
void QQMusic::onPlayAll(PageType pageType)
{
    CommonPage* page = nullptr;
     switch(pageType)
     {
     case PageType::LIKE_PAGE:
         page = ui->likePage;
        break;
     case PageType::LOCAL_PAGE:
        page = ui->localPage;
        break;
     case PageType::HISTORY_PAGE:
        page = ui->recentPage;
         break;
     default:
        qDebug()<<"扩展";
     }
     playAllOfCommonPage(page, 0);
}

void QQMusic::playAllOfCommonPage(CommonPage *commonPage, int index)
{
    curPage = commonPage;
    playList->clear();
    ui->localPage->addMusicToPlayer(musicList, playList);
    playList->setCurrentIndex(index);
    player->play();
}




void QQMusic::connectSignalAndSlot()
 {
    //  ⾃定义的btFrom按钮点击信号，当btForm点击后，设置对应的堆叠窗⼝

     connect(ui->Rec, &btForm::click, this, &QQMusic::onBtFormClick);
     connect(ui->music, &btForm::click, this, &QQMusic::onBtFormClick);
     connect(ui->audio, &btForm::click, this, &QQMusic::onBtFormClick);
     connect(ui->like, &btForm::click, this, &QQMusic::onBtFormClick);
     connect(ui->local, &btForm::click, this, &QQMusic::onBtFormClick);
     connect(ui->Recent, &btForm::click, this, &QQMusic::onBtFormClick);

     connect(ui->likePage, &CommonPage::updateLikeMusic, this,&QQMusic::onUpdateLikeMusic);
     connect(ui->localPage, &CommonPage::updateLikeMusic, this,&QQMusic::onUpdateLikeMusic);
     connect(ui->recentPage, &CommonPage::updateLikeMusic, this,&QQMusic::onUpdateLikeMusic);
     connect(ui->play, &QPushButton::clicked, this, &QQMusic::onPlayMusic);

     connect(ui->playUp, &QPushButton::clicked, this, &QQMusic::onPlayUpCliked);
     connect(ui->playDown, &QPushButton::clicked, this, &QQMusic::onPlayDownCliked);

     connect(ui->likePage, &CommonPage::playAll, this, &QQMusic::onPlayAll);
     connect(ui->localPage, &CommonPage::playAll, this, &QQMusic::onPlayAll);
     connect(ui->recentPage, &CommonPage::playAll, this, &QQMusic::onPlayAll);

     connect(ui->likePage, &CommonPage::playMusicByIndex, this,&QQMusic::playMusicByIndex_);
     connect(ui->localPage, &CommonPage::playMusicByIndex, this,&QQMusic::playMusicByIndex_);
     connect(ui->recentPage, &CommonPage::playMusicByIndex, this,&QQMusic::playMusicByIndex_);
     connect(volumeTool, &VolumeTool::setMusicVolume, this, &QQMusic::setPlayerVolume);

     connect(player, &QMediaPlayer::positionChanged, this,  &QQMusic::onPositionChanged);
     connect(ui->processBar, &MusicSlider::setMusicSliderPosition,this, &QQMusic::onMusicSliderChanged);

     connect(ui->lrcWord, &QPushButton::clicked, this, &QQMusic::onLrcWordClicked);


}

void QQMusic::onUpdateLikeMusic(bool isLike, QString musicId)
{
    auto it = musicList.findMusicById(musicId);
     if(it != musicList.end())
     {
     it->setIsLike(isLike);
     }

     ui->likePage->reFresh(musicList);
     ui->localPage->reFresh(musicList);
     ui->recentPage->reFresh(musicList);
}
void QQMusic::onBtFormClick(int id)
 {
 // 1.获取当前⻚⾯所有btFrom按钮类型的对象

    QList<btForm*> buttonList = this->findChildren<btForm*>();
 // 2.遍历所有对象, 如果不是当前id的按钮,则把之前设置的背景颜⾊清除掉

    foreach (btForm* btitem, buttonList)
    {
        if (id  != btitem->getId())
        {
            btitem->clearBg();
        }
    }
    // 3.设置当前栈空间显⽰⻚⾯
    ui->stackedWidget->setCurrentIndex(id - 1);
}


void QQMusic::onCurrentIndexChanged(int index)
{
    currentIndex = index;
    const QString& musicId = curPage->getMusicIdByIndex(index);
    auto it = musicList.findMusicById(musicId);
    if(it != musicList.end())
    {
        it->setIsHistory(true);
    }
    ui->recentPage->reFresh(musicList);

}

void QQMusic::setMusicSilence(bool isMuted)
{
    player->setMuted(isMuted);
}


void QQMusic::onMetaDataAvailableChangedChanged(bool available)
{
    QString singer = player->metaData("Author").toStringList().join(",");
    QString musicName = player->metaData("Title").toString();
    auto it = musicList.findMusicById((curPage -> getMusicIdByIndex(currentIndex)));
    if(musicName.isEmpty())
     {

         if(it != musicList.end())
         {
             musicName = it->getMusicName();
             singer = it->getSingexrName();
         }
     }
     ui->MusicName->setText(musicName);
     ui->MusicSinger->setText(singer);
     lrcPage->setMusicName(musicName);      // 假设lrcPage有setMusicName方法
     lrcPage->setSingerName(singer);       // 假设lrcPage有setMusicSinger方法
     QVariant coverImage = player->metaData("ThumbnailImage");
      if(coverImage.isValid())
      {
          QImage image = coverImage.value<QImage>();

          ui->MusicCover->setPixmap(QPixmap::fromImage(image));
          ui->MusicCover->setScaledContents(true);
          curPage->setImageLabel(QPixmap::fromImage(image));
      }
      else {
          qDebug()<<"No Picture";
      }
      if(it !=musicList.end())
      {
          QString lrcPath = it ->getLrcFilePath();
          lrcPage->parseLrc(lrcPath);
      }
}

void QQMusic::onLrcWordClicked()
{
    lrcPage->show();
    lrcAnimation->start();
}



void QQMusic::onDurationChanged(qint64 duration)
{
    totalDuration = duration;
    ui->totalTime->setText(QString("%1:%2").arg(duration/1000/60, 2, 10,
    QChar('0')).arg(duration/1000%60,2,10, QChar('0')));
}

void QQMusic::onPositionChanged(qint64 position)
{

    ui->currentTime->setText(QString("%1:%2").arg(position/1000/60, 2, 10, QChar('0')).arg(position/1000%60,2,10, QChar('0')));
    ui->processBar->setStep((float)position/(float)totalDuration);
    if(playList->currentIndex() >= 0)
    {
        lrcPage->showLrcWord(position);
    }
}

void QQMusic::onMusicSliderChanged(float value)
{    
    if (totalDuration <= 0) return;
    qint64 duration = (qint64)(totalDuration * value);
    ui->currentTime->setText(QString("%1:%2").arg(duration/1000/60, 2, 10, QChar('0')).arg(duration/1000%60,2,10, QChar('0')));
    player->setPosition(duration);
}

void QQMusic::setPlayerVolume(int volume)
{
    player->setVolume(volume);
}

void QQMusic::onPlayStateChanged()
{

    if(player->state() == QMediaPlayer::PlayingState)
    {
       // 播放状态
       ui->play->setIcon(QIcon(":/play_on.png"));
    }
    else
    {
       // 暂停状态
       ui->play->setIcon(QIcon(":/play3.png"));
    }
}
QQMusic::~QQMusic()
{
    delete ui;
}
//关闭窗口
void QQMusic::on_quit_clicked()
{
    musicList.writeToDB();
    sqlite.close();
    window()->close();
}
//最小化窗口
void QQMusic::on_min_clicked()
{
    this->showMinimized(); // 最小化当前窗口
}
//音量按钮
void QQMusic::on_volumn_clicked()
{
  //先调整窗口的显示位置，否则该窗口在主窗口的左上角

    //1.获取该按钮左上角坐标，并且从窗口坐标转化为全局坐标：因为弹窗时基于全局坐标
     QPoint point = ui->volumn->mapToGlobal(QPoint(0,0));
    //2.计算volume窗口的左上角位置
    //让该窗口显示在鼠标点击的正上方
    //鼠标位置：减去窗口宽度的一半，以及高度恰好就是窗口的左上角
     QPoint volumeLeftTop =  point - QPoint(volumeTool->width()/2, volumeTool -> height());

    //微调窗口位置
     volumeLeftTop.setY(volumeLeftTop.y()+30);
     volumeLeftTop.setX(volumeLeftTop.x()+15);

    //3.移动窗口位置
    volumeTool->move(volumeLeftTop);

    //4.将窗口显示出来
    volumeTool->show();
}

void QQMusic::on_addLocal_clicked()
{
    //1.创建一个文件对话框
    QFileDialog fileDialog(this);
    //设置对话框标题
    fileDialog.setWindowTitle("添加本地下载音乐");

    // 2.创建一个打开格式的文件对话框
    fileDialog.setAcceptMode(QFileDialog::AcceptOpen);

    //3.设置对话框模式
    //只能选择文件，并且一次性可以选择多个存在的文件
    fileDialog.setFileMode(QFileDialog::ExistingFiles);

    //4.设置对话框MIME过滤器
    QStringList mimeList;
    mimeList<<"application/octet-stream";
    fileDialog.setMimeTypeFilters(mimeList);

    //5.设置对话框默认打开路径，设置目录为当前工程错在目录
    QDir dir(QDir::currentPath());
    dir.cdUp();
    QString musicPath = dir.path()+"/QQMusic/musics/";
    fileDialog.setDirectory(musicPath);

    //6.显示对话框，并接收返回值
    //模态对话框，exec内部是死循环处理
    if(fileDialog.exec() == QFileDialog::Accepted)
    {
        //切换到本地音乐界面，因为加载完的音乐需要在本地音乐界面显示
        ui->stackedWidget->setCurrentIndex(4);
        //获取对话框的返回值
        QList<QUrl> fileUrls = fileDialog.selectedUrls();
        // 拿到歌曲⽂件后，将歌曲⽂件交由musicList进⾏管理
        musicList.addMusicByUrl(fileUrls);
        //更新到本地音乐系列
        ui->localPage->reFresh(musicList);
        //添加歌曲到歌曲列表当中
        ui->localPage->addMusicToPlayer(musicList,playList);

    }
}

void QQMusic::onPlayMusic()
{
    if (musicList.empty()) {
          qDebug() << "musicList is Empty!";
          return;
      }

     if(player->state() == QMediaPlayer::PlayingState)
     {
        player->pause();
     }
     else if(player->state() == QMediaPlayer::PausedState)
     {
        player->play();
     }
     else if(player->state() == QMediaPlayer::StoppedState)
     {
        player->play();
     }
}

void QQMusic::onPlayUpCliked()
{
    playList->previous();
}

void QQMusic::onPlayDownCliked()
{
         playList->next();
}

void QQMusic::onPlaybackModeCliked()
{
    if(playList->playbackMode() == QMediaPlaylist::Loop)
    {
        ui->playMode->setToolTip("随机播放");
        playList->setPlaybackMode(QMediaPlaylist::Random);
    }
    else if(playList->playbackMode() == QMediaPlaylist::Random)
     {
        ui->playMode->setToolTip("单曲循环");
        playList->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
    }
    else if(playList->playbackMode() == QMediaPlaylist::CurrentItemInLoop)
    {
        ui->playMode->setToolTip("列表循环");
        playList->setPlaybackMode(QMediaPlaylist::Loop);
    }
    else
     {
        qDebug()<<"播放模式错误";
     }

}

void QQMusic::onPlaybackModeChanged(QMediaPlaylist::PlaybackMode playbackMode)
 {
     if(playbackMode == QMediaPlaylist::Loop)
     {
        ui->playMode->setIcon(QIcon(":/list_play.png"));
     }
     else if(playbackMode == QMediaPlaylist::Random)
     {
        ui->playMode->setIcon(QIcon(":/shuffle_2.png"));
     }
     else if(playbackMode == QMediaPlaylist::CurrentItemInLoop)
     {
        ui->playMode->setIcon(QIcon(":/single_play.png"));
     }
     else
     {
        qDebug()<<"暂不⽀持该模式";
     }
}

void QQMusic::on_connectDB_clicked()
{
//    QSqlDatabase db =  QSqlDatabase::addDatabase("QSQLITE");
//    db.setDatabaseName("QQMusic.db");
//    if(!db.open())
//     {
//     qDebug()<<"QQMusic:"<<db.lastError().text();
//     }
//     qDebug()<<"SQLite creat successful!!";
//     db.close();
}
